[id].vue 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275
  1. <template>
  2. <div class="admin--page-content">
  3. <div class="admin--form">
  4. <table class="admin--form--table">
  5. <colgroup>
  6. <col style="width: 140px;">
  7. <col>
  8. </colgroup>
  9. <tbody>
  10. <tr>
  11. <th><div>분야</div></th>
  12. <td>{{ data.field_name || "-" }}</td>
  13. </tr>
  14. <tr>
  15. <th><div>지역</div></th>
  16. <td>{{ data.area_name || "-" }}</td>
  17. </tr>
  18. <tr>
  19. <th><div>선상명</div></th>
  20. <td class="admin--table-title">{{ data.name || "-" }}</td>
  21. </tr>
  22. <tr>
  23. <th><div>낚시지역</div></th>
  24. <td>{{ data.area_detail || "-" }}</td>
  25. </tr>
  26. <tr>
  27. <th><div>중량(톤수)</div></th>
  28. <td>{{ data.tonnage || "-" }}</td>
  29. </tr>
  30. <tr>
  31. <th><div>탑승인원</div></th>
  32. <td>{{ data.capacity || "-" }}</td>
  33. </tr>
  34. <tr>
  35. <th><div>우편번호</div></th>
  36. <td>{{ data.zip_code || "-" }}</td>
  37. </tr>
  38. <tr>
  39. <th><div>주소</div></th>
  40. <td>{{ data.address || "-" }}</td>
  41. </tr>
  42. <tr>
  43. <th><div>상세주소</div></th>
  44. <td>{{ data.address_detail || "-" }}</td>
  45. </tr>
  46. <tr>
  47. <th><div>참고항목</div></th>
  48. <td>{{ data.address_refer || "-" }}</td>
  49. </tr>
  50. <tr>
  51. <th><div>좌표</div></th>
  52. <td>
  53. <template v-if="data.lat && data.lng">{{ data.lat }}, {{ data.lng }}</template>
  54. <template v-else>-</template>
  55. </td>
  56. </tr>
  57. <tr>
  58. <th><div>사진</div></th>
  59. <td>
  60. <div v-if="data.photos && data.photos.length" class="onboard--photo-grid">
  61. <div v-for="p in data.photos" :key="p.id" class="onboard--photo-item">
  62. <img :src="getImageUrl(p.file_path)" :alt="p.original_name" />
  63. </div>
  64. </div>
  65. <template v-else>-</template>
  66. </td>
  67. </tr>
  68. <tr>
  69. <th><div>제휴 여부</div></th>
  70. <td>
  71. <span :class="['admin--badge', data.partnership_YN === 'Y' ? 'admin--badge-active' : 'admin--badge-ended']">
  72. {{ data.partnership_YN === "Y" ? "제휴" : "비제휴" }}
  73. </span>
  74. </td>
  75. </tr>
  76. <tr v-if="data.partnership_YN === 'Y'">
  77. <th><div>계좌번호</div></th>
  78. <td>
  79. <template v-if="data.account_number">
  80. {{ bankName(data.bank_code) }} {{ data.account_number }}<template v-if="data.account_holder"> ({{ data.account_holder }})</template>
  81. </template>
  82. <template v-else>-</template>
  83. </td>
  84. </tr>
  85. <tr>
  86. <th><div>상태</div></th>
  87. <td>
  88. <span :class="['admin--badge', data.status_YN === 'Y' ? 'admin--badge-active' : 'admin--badge-ended']">
  89. {{ data.status_YN === "Y" ? "사용중" : "미사용" }}
  90. </span>
  91. </td>
  92. </tr>
  93. <tr>
  94. <th><div>등록일</div></th>
  95. <td>{{ formatDateTime(data.created_at) }}</td>
  96. </tr>
  97. <tr>
  98. <th><div>최근 수정</div></th>
  99. <td>{{ formatDateTime(data.updated_at) }}</td>
  100. </tr>
  101. </tbody>
  102. </table>
  103. <!-- 버튼 영역 -->
  104. <div class="admin--form-actions">
  105. <button type="button" class="admin--btn" @click="goToList">
  106. ← 목록으로
  107. </button>
  108. <button type="button" class="admin--btn admin--btn-red-border ml--auto" @click="handleDelete">
  109. 삭제
  110. </button>
  111. <button type="button" class="admin--btn admin--btn-red" @click="goToEdit">
  112. 수정
  113. </button>
  114. </div>
  115. <!-- 알림 모달 -->
  116. <AdminAlertModal
  117. v-if="alertModal.show"
  118. :title="alertModal.title"
  119. :message="alertModal.message"
  120. :type="alertModal.type"
  121. @confirm="handleAlertConfirm"
  122. @cancel="handleAlertCancel"
  123. @close="closeAlertModal"
  124. />
  125. </div>
  126. </div>
  127. </template>
  128. <script setup>
  129. import { ref, onMounted } from "vue";
  130. import { useRoute, useRouter } from "vue-router";
  131. import AdminAlertModal from "~/components/admin/AdminAlertModal.vue";
  132. definePageMeta({
  133. layout: "admin",
  134. middleware: ["auth"],
  135. });
  136. const route = useRoute();
  137. const router = useRouter();
  138. const { get, del } = useApi();
  139. const { getImageUrl } = useImage();
  140. const onboardId = route.params.id;
  141. const data = ref({
  142. field_name: "",
  143. area_name: "",
  144. name: "",
  145. area_detail: "",
  146. tonnage: "",
  147. capacity: "",
  148. zip_code: "",
  149. address: "",
  150. address_detail: "",
  151. address_refer: "",
  152. lat: "",
  153. lng: "",
  154. bank_code: "",
  155. account_number: "",
  156. account_holder: "",
  157. partnership_YN: "N",
  158. status_YN: "Y",
  159. created_at: "",
  160. updated_at: "",
  161. photos: [],
  162. });
  163. // 은행 코드 → 은행명
  164. const bankMap = {
  165. "002": "산업은행", "003": "기업은행", "004": "국민은행", "007": "수협은행",
  166. "011": "농협은행", "020": "우리은행", "023": "SC제일은행", "031": "대구은행",
  167. "032": "부산은행", "034": "광주은행", "035": "제주은행", "037": "전북은행",
  168. "039": "경남은행", "045": "새마을금고", "071": "우체국", "081": "하나은행",
  169. "088": "신한은행", "089": "케이뱅크", "090": "카카오뱅크", "092": "토스뱅크",
  170. };
  171. const bankName = (code) => bankMap[code] || (code ? code : "-");
  172. // 알림 모달
  173. const alertModal = ref({
  174. show: false,
  175. title: "알림",
  176. message: "",
  177. type: "alert",
  178. onConfirm: null,
  179. });
  180. const showAlert = (message, title = "알림") => {
  181. alertModal.value = { show: true, title, message, type: "alert", onConfirm: null };
  182. };
  183. const showConfirm = (message, onConfirm, title = "확인") => {
  184. alertModal.value = { show: true, title, message, type: "confirm", onConfirm };
  185. };
  186. const closeAlertModal = () => { alertModal.value.show = false; };
  187. const handleAlertConfirm = () => {
  188. if (alertModal.value.onConfirm) alertModal.value.onConfirm();
  189. closeAlertModal();
  190. };
  191. const handleAlertCancel = () => closeAlertModal();
  192. // 상세 조회
  193. const loadDetail = async () => {
  194. const { data: res, error } = await get(`/onboard/${onboardId}`);
  195. if (error || !res?.success) {
  196. showAlert(error?.message || res?.message || "조회에 실패했습니다.", "오류");
  197. return;
  198. }
  199. const row = res.data || {};
  200. data.value = {
  201. field_name: row.field_name ?? "",
  202. area_name: row.area_name ?? "",
  203. name: row.name ?? "",
  204. area_detail: row.area_detail ?? "",
  205. tonnage: row.tonnage ?? "",
  206. capacity: row.capacity ?? "",
  207. zip_code: row.zip_code ?? "",
  208. address: row.address ?? "",
  209. address_detail: row.address_detail ?? "",
  210. address_refer: row.address_refer ?? "",
  211. lat: row.lat ?? "",
  212. lng: row.lng ?? "",
  213. bank_code: row.bank_code ?? "",
  214. account_number: row.account_number ?? "",
  215. account_holder: row.account_holder ?? "",
  216. partnership_YN: row.partnership_YN ?? "N",
  217. status_YN: row.status_YN ?? "Y",
  218. created_at: row.created_at ?? "",
  219. updated_at: row.updated_at ?? "",
  220. photos: row.photos ?? [],
  221. };
  222. };
  223. // 삭제
  224. const handleDelete = () => {
  225. showConfirm(
  226. `'${data.value.name}' 선상을 삭제하시겠습니까?`,
  227. async () => {
  228. const { data: res, error } = await del(`/onboard/${onboardId}`);
  229. if (error || !res?.success) {
  230. showAlert(error?.message || res?.message || "삭제에 실패했습니다.", "오류");
  231. } else {
  232. showAlert(res.message || "삭제되었습니다.", "성공");
  233. setTimeout(() => router.push("/site-manager/onboard/list"), 800);
  234. }
  235. },
  236. "선상 삭제"
  237. );
  238. };
  239. // 이동
  240. const goToList = () => router.push("/site-manager/onboard/list");
  241. const goToEdit = () => router.push(`/site-manager/onboard/edit/${onboardId}`);
  242. // 일시 포맷
  243. const formatDateTime = (dateString) => {
  244. if (!dateString) return "-";
  245. const date = new Date(dateString.replace(" ", "T"));
  246. if (isNaN(date.getTime())) return dateString;
  247. return date.toLocaleString("ko-KR", {
  248. year: "numeric",
  249. month: "2-digit",
  250. day: "2-digit",
  251. hour: "2-digit",
  252. minute: "2-digit",
  253. });
  254. };
  255. onMounted(() => {
  256. loadDetail();
  257. });
  258. </script>